package com.ms.domain.validator;

import com.ms.exception.DpwcSpringValidationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.validation.MapBindingResult;
import org.springframework.validation.Validator;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * User: gmc
 * Date: 02/04/13
 */
public class ValidationService {
    @Autowired
    @Qualifier("validator")
    Validator validatorJsr303;

    @Autowired
    List<Validator> validatorList;


    public void validate(Object object, ValidationLevel validationLevel) {
        if (ValidationLevel.FIRST == validationLevel) {
            validateFirstLevel(object);
        } else if (ValidationLevel.SECOND == validationLevel) {
            validateSecondLevel(object);
        } else if (ValidationLevel.ALL == validationLevel) {
            validate(object);
        }
    }

    public void validate(Object object) {
        Map<String, String> map = new HashMap<String, String>();
        MapBindingResult errors = new MapBindingResult(map, object.getClass().getName());
        validate(object, errors);
    }

    private void validate(Object object, MapBindingResult errors) {
        validateFirstLevel(object, errors);
        validateSecondLevel(object, errors);
    }


    public void validateFirstLevel(Object object) {
        Map<String, String> map = new HashMap<String, String>();
        MapBindingResult errors = new MapBindingResult(map, object.getClass().getName());
        validateFirstLevel(object, errors);
    }

    protected void validateFirstLevel(Object object, MapBindingResult errors) {
        validatorJsr303.validate(object, errors);
        if (errors.hasErrors()) {
            throw new DpwcSpringValidationException(errors, true);
        }
    }

    public void validateSecondLevel(Object object) {
        Map<String, String> map = new HashMap<String, String>();
        MapBindingResult errors = new MapBindingResult(map, object.getClass().getName());
        validateSecondLevel(object, errors);
    }

    protected void validateSecondLevel(Object object, MapBindingResult errors) {
        List<Validator> validators = getValidatorsFor(object);
        for (Validator validator1 : validators) {
            validator1.validate(object, errors);
            if (errors.hasErrors()) {
                throw new DpwcSpringValidationException(errors, false);
            }
        }
    }

    protected List<Validator> getValidatorsFor(Object object) {
        List<Validator> objectValidators = new ArrayList<Validator>();
        for (Validator validator1 : validatorList) {
            if (validator1 instanceof LocalValidatorFactoryBean) {
                continue;
            }
            if (validator1.supports(object.getClass())) {
                objectValidators.add(validator1);
            }
        }
        return objectValidators;
    }

}
